package com.smsc.headend.task.engine.handler.impl.firmware;

import com.smsc.headend.common.enums.errorcode.TaskExecuteErrorCode;
import com.smsc.headend.module.fwu.entity.TemplateFwUpgrade;
import com.smsc.headend.module.protocol.DeviceData;
import com.smsc.headend.module.task.dto.AtomicTask;
import com.smsc.headend.module.task.dto.AtomicTaskState;
import com.smsc.headend.module.task.dto.Task;
import com.smsc.headend.module.task.enums.TaskType;
import com.smsc.headend.task.engine.dao.TaskDAO;
import com.smsc.headend.task.engine.exception.UDISTaskHandlerException;
import com.smsc.headend.task.engine.handler.TaskHandler;
import com.smsc.headend.task.engine.service.FeignAssetManagementService;
import com.smsc.headend.task.engine.service.firmware.FirmwareService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

/**
 * 验证镜像和调用激活状态时，返回success这正常继续执行
 * 返回TemporaryFailure，休眠两秒后，重新生成同样的atomicTask，再次获取状态
 * 其他结果则为执行失败
 *
 * @author liangli
 * @implNote Blue_Book_edition_12-2.pdf   chapter 4.4.6 Image transfer
 * @date 2020/9/25
 */
@Slf4j
public class ImageTransferVerifyAndActivationHandler implements TaskHandler {

    @Autowired
    TaskDAO taskDAO;
    @Autowired
    FeignAssetManagementService assetManagementService;
    @Value("#{T(java.lang.Integer).parseInt('${fwu.step.retryTimes:2}')}")
    Integer firmwareStepsRetry;
    @Autowired
    FirmwareService firmwareService;

    @Override
    public int handle(Task task, AtomicTask atomicTask, DeviceData cosemData, String actionResult) throws UDISTaskHandlerException {
        Integer result = -1;
        if ("success".equalsIgnoreCase(actionResult)) {
            result = 1;
            firmwareService.saveFwuReport(task, atomicTask, result, TemplateFwUpgrade.TaskType.ImageActivation, null, null);
            if (TaskType.FirmwareImageActivation.toString().equalsIgnoreCase(task.getTaskType())) {
                log.info("actication success. remove old get status task taskNo={}, comId={},meterId={}", task.getTaskNo(), task.getComId(), task.getMeterId());
                taskDAO.atomicTaskQueuePopReverse(task.getTaskNo());
            }
            return result;
        }

        if ("TemporaryFailure".equalsIgnoreCase(actionResult)) {
            log.info("{} :  TemporaryFailure, waiting 2seconds get status, comId={}, meterId={}, taskNo={}", task.getTaskType(), task.getComId(), task.getMeterId(), task.getTaskNo());
            try {
                Thread.sleep(2000l);
            } catch (InterruptedException e) {
                log.error("waiting for generate next verify task failed: meterId={}, comId={}", task.getMeterId(), task.getComId());
                return -1;
            }
            return 1;
        }

        log.info("{} firmware image verify failed {} ", task.getTaskNo(), actionResult);
        firmwareService.saveFwuReport(task, atomicTask, result, TemplateFwUpgrade.TaskType.ImageActivation, null, null);
        return result;
    }

    @Override
    public int handleFailure(Task task, AtomicTask atomicTask, String message) {
        if (firmwareService.isRetryMessageType(message)) {
            AtomicTaskState atomicTaskState = taskDAO.hashGetAtomicTaskState(atomicTask.getAtomicTaskNo());
            if (atomicTaskState.getRetryTimes() >= firmwareStepsRetry) {
                log.error("Image transfer failed retry times over");
                firmwareService.saveFwuReport(task, atomicTask, -1, TemplateFwUpgrade.TaskType.ImageActivation, null, null);
                return -1;
            }
            log.error("Image transfer failed retry times {}", atomicTaskState.getRetryTimes());
            atomicTaskState.setStored(false);
            taskDAO.hashSetAtomicTaskState(atomicTask.getAtomicTaskNo(), task, atomicTaskState.getRetryTimes() + 1,  atomicTaskState);
            return 0;
        }
        firmwareService.saveFwuReport(task, atomicTask, -1, TemplateFwUpgrade.TaskType.ImageActivation, null, null);
        log.error("stop this task, comId={},meterId={},type={}, messsage={}", task.getComId(), task.getMeterId(), task.getTaskType(), message);
        return -1;
    }
}
